package com.srmt.document.feishu.internal.table.impl.normal;

import com.lark.oapi.service.docx.v1.model.*;
import com.srmt.document.exception.DocumentOperationException;
import com.srmt.document.exception.TableException;
import com.srmt.document.feishu.internal.core.BlockContext;
import com.srmt.document.feishu.internal.core.BlockUtils;
import com.srmt.document.feishu.internal.table.model.TableContext;
import com.srmt.document.model.ColumnData;
import com.srmt.document.model.RowData;
import com.srmt.feishu.client.FeishuClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 普通表格写入操作
 *
 * 封装所有与Normal Table写入相关的操作，包括：
 * - 单元格内容更新
 * - 批量单元格更新
 * - 行操作（添加/删除）
 * - 列操作（添加/删除）
 *
 * @author srmt
 * @since 3.0.0
 */
public class NormalTableWriteOps {

    private static final Logger logger = LoggerFactory.getLogger(NormalTableWriteOps.class);

    private final FeishuClient client;
    private final NormalTableReadOps readOps;

    public NormalTableWriteOps(FeishuClient client, NormalTableReadOps readOps) {
        if (client == null) {
            throw new IllegalArgumentException("客户端不能为null");
        }
        if (readOps == null) {
            throw new IllegalArgumentException("ReadOps 不能为null");
        }
        this.client = client;
        this.readOps = readOps;
    }

    /**
     * 更新单个单元格内容
     */
    public void updateCellContentByIndex(TableContext context, int row, int col, String value,
                                        String cellBlockId) throws TableException {
        logger.debug("更新 normal table cell [{}, {}] with value: {}", row, col, value);

        try {
            BlockContext blockContext = context.getBlockContext();

            // 获取单元格Block
            Block cellBlock = blockContext.getBlockById(cellBlockId);
            if (cellBlock == null) {
                throw new TableException("单元格 block 未找到: " + cellBlockId);
            }

            // 获取单元格的子Block（通常是Text Block）
            List<Block> children = blockContext.findChildrenBlocks(cellBlockId);
            if (children.isEmpty()) {
                throw new TableException("单元格 has no text block");
            }

            // 更新第一个文本Block
            Block textBlock = children.get(0);
            String textBlockId = textBlock.getBlockId();

            // 创建新的文本元素
            TextElement[] elements = BlockUtils.createTextElements(value);

            // 构建更新请求
            UpdateTextElementsRequest updateReq = UpdateTextElementsRequest.newBuilder()
                    .elements(elements)
                    .build();

            UpdateBlockRequest blockUpdateReq = UpdateBlockRequest.newBuilder()
                    .blockId(textBlockId)
                    .updateTextElements(updateReq)
                    .build();

            PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                    .documentId(context.getDocumentId())
                    .blockId(textBlockId)
                    .updateBlockRequest(blockUpdateReq)
                    .build();

            // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
            client.docx().patchDocumentBlock(patchReq);

            logger.debug("单元格内容更新成功");

        } catch (Exception e) {
            throw new TableException("(更新单元格内容: " + e.getMessage());
        }
    }

    /**
     * 批量更新单元格内容
     */
    public void batchUpdateCellsByIndex(TableContext context, Map<int[], String> cellUpdates,
                                       java.util.function.BiFunction<TableContext, int[], String> cellLocator)
            throws TableException {
        if (cellUpdates == null || cellUpdates.isEmpty()) {
            return;
        }

        logger.debug("批量更新普通表格中的{}个单元格", cellUpdates.size());

        // 转换为基于Block ID的更新映射
        Map<String, String> blockIdUpdates = new HashMap<>();

        for (Map.Entry<int[], String> entry : cellUpdates.entrySet()) {
            int[] position = entry.getKey();
            if (position == null || position.length < 2) {
                logger.warn("无效的位置数组, skipping");
                continue;
            }

            String value = entry.getValue();

            try {
                // 定位单元格的Block ID
                String cellBlockId = cellLocator.apply(context, position);
                blockIdUpdates.put(cellBlockId, value);
            } catch (Exception e) {
                logger.error("(locate cell [{}, {}]: {}", position[0], position[1], e.getMessage());
                throw new TableException("(locate cell");
            }
        }

        if (!blockIdUpdates.isEmpty()) {
            // 直接构建批量更新请求
            List<UpdateBlockRequest> requests = new ArrayList<>();
            BlockContext blockContext = context.getBlockContext();

            for (Map.Entry<String, String> entry : blockIdUpdates.entrySet()) {
                String cellBlockId = entry.getKey();
                String value = entry.getValue();

                try {
                    // 获取单元格的文本Block
                    List<Block> children = blockContext.findChildrenBlocks(cellBlockId);
                    if (!children.isEmpty()) {
                        Block textBlock = children.get(0);
                        String textBlockId = textBlock.getBlockId();

                        // 创建更新请求
                        TextElement[] elements = BlockUtils.createTextElements(value);

                        UpdateTextElementsRequest updateTextReq = UpdateTextElementsRequest.newBuilder()
                                .elements(elements)
                                .build();

                        UpdateBlockRequest updateReq = UpdateBlockRequest.newBuilder()
                                .blockId(textBlockId)
                                .updateTextElements(updateTextReq)
                                .build();

                        requests.add(updateReq);
                    }
                } catch (Exception e) {
                    logger.error("(create update request for cell {}: {}",
                               cellBlockId, e.getMessage());
                }
            }

            // 执行批量更新
            if (!requests.isEmpty()) {
                try {
                    BatchUpdateDocumentBlockReq batchReq = BatchUpdateDocumentBlockReq.newBuilder()
                            .documentId(context.getDocumentId())
                            .documentRevisionId(-1)
                            .batchUpdateDocumentBlockReqBody(BatchUpdateDocumentBlockReqBody.newBuilder()
                                    .requests(requests.toArray(new UpdateBlockRequest[0]))
                                    .build())
                            .build();

                    // batchUpdateDocumentBlock现在直接返回数据体，失败时抛出FeishuApiException
                    client.docx().batchUpdateDocumentBlock(batchReq);

                    logger.info("成功批量更新普通表格中的{}个单元格", blockIdUpdates.size());
                } catch (Exception e) {
                    throw new TableException("(batch update cells: " + e.getMessage());
                }
            }
        }
    }

    /**
     * 添加表格行
     */
    public void addTableRows(TableContext context, List<RowData> rows, int position,
                            java.util.function.BiFunction<TableContext, int[], String> cellLocator)
            throws TableException {
        try {
            // 获取表格维度信息
            int[] dimensions = readOps.getTableDimensions(context);
            int currentRowCount = dimensions[0];
            int columnCount = dimensions[1];

            // 获取文档ID和表格Block ID
            String docId = context.getDocumentId();
            String tableBlockId = context.getTableBlockId();

            // 逐行插入
            for (int i = 0; i < rows.size(); i++) {
                RowData rowData = rows.get(i);

                // 计算实际插入位置
                int actualPosition;
                if (position < 0) {
                    actualPosition = -1;  // 追加到末尾
                } else {
                    actualPosition = position + i + 1;
                }

                // 构建插入行请求
                InsertTableRowRequest insertReq = InsertTableRowRequest.newBuilder()
                        .rowIndex(actualPosition)
                        .build();

                UpdateBlockRequest updateReq = UpdateBlockRequest.newBuilder()
                        .blockId(tableBlockId)
                        .insertTableRow(insertReq)
                        .build();

                PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                        .documentId(docId)
                        .blockId(tableBlockId)
                        .updateBlockRequest(updateReq)
                        .build();

                // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
                client.docx().patchDocumentBlock(patchReq);

                // 刷新上下文
                context = refreshContext(context, docId);

                // 更新单元格内容
                if (rowData.getCells() != null && !rowData.getCells().isEmpty()) {
                    int newRowIndex = (actualPosition == -1) ? currentRowCount + i : actualPosition;

                    for (int col = 0; col < Math.min(rowData.getCells().size(), columnCount); col++) {
                        String cellValue = rowData.getCells().get(col);
                        if (cellValue != null && !cellValue.isEmpty()) {
                            String cellBlockId = cellLocator.apply(context, new int[]{newRowIndex, col});
                            updateCellContentInternal(context, cellBlockId, cellValue);
                        }
                    }
                }
            }

            logger.info("成功向普通表格添加{}行", rows.size());

        } catch (TableException e) {
            throw e;
        } catch (Exception e) {
            throw new TableException("向普通表格添加行失败: " + e.getMessage());
        }
    }

    /**
     * 删除表格行
     */
    public void deleteTableRows(TableContext context, int startRow, int endRow)
            throws TableException {
        // 接口定义从1开始，需要转换
        startRow--;

        logger.debug("删除 rows {} to {} from normal table", startRow, endRow);

        try {
            String tableBlockId = context.getTableBlockId();
            String docId = context.getDocumentId();

            // 构建删除行请求
            DeleteTableRowsRequest deleteReq = DeleteTableRowsRequest.newBuilder()
                    .rowStartIndex(startRow)
                    .rowEndIndex(endRow)
                    .build();

            UpdateBlockRequest updateReq = UpdateBlockRequest.newBuilder()
                    .blockId(tableBlockId)
                    .deleteTableRows(deleteReq)
                    .build();

            PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                    .documentId(docId)
                    .blockId(tableBlockId)
                    .documentRevisionId(-1)
                    .updateBlockRequest(updateReq)
                    .build();

            // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
            client.docx().patchDocumentBlock(patchReq);

            logger.info("成功从普通表格删除第{}到第{}行", startRow, endRow);

        } catch (TableException e) {
            throw e;
        } catch (Exception e) {
            throw new TableException("(delete table rows: " + e.getMessage());
        }
    }

    /**
     * 添加表格列
     */
    public void addTableColumns(TableContext context, List<ColumnData> columns, int position,
                               java.util.function.BiFunction<TableContext, int[], String> cellLocator)
            throws TableException {
        if (columns == null || columns.isEmpty()) {
            logger.debug("没有需要添加的列");
            return;
        }

        logger.debug("在位置{}向普通表格添加{}列", position, columns.size());

        try {
            // 获取表格维度信息
            int[] dimensions = readOps.getTableDimensions(context);
            int rowCount = dimensions[0];
            int currentColumnCount = dimensions[1];

            // 获取文档ID和表格Block ID
            String docId = context.getDocumentId();
            String tableBlockId = context.getTableBlockId();

            // 逐列插入
            for (int i = 0; i < columns.size(); i++) {
                ColumnData columnData = columns.get(i);

                // 计算实际插入位置
                int actualPosition;
                if (position < 0) {
                    actualPosition = -1;  // 追加到末尾
                } else {
                    actualPosition = position + i + 1;
                }

                // 构建插入列请求
                InsertTableColumnRequest insertReq = InsertTableColumnRequest.newBuilder()
                        .columnIndex(actualPosition)
                        .build();

                UpdateBlockRequest updateReq = UpdateBlockRequest.newBuilder()
                        .blockId(tableBlockId)
                        .insertTableColumn(insertReq)
                        .build();

                PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                        .documentId(docId)
                        .blockId(tableBlockId)
                        .documentRevisionId(-1)
                        .updateBlockRequest(updateReq)
                        .build();

                // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
                client.docx().patchDocumentBlock(patchReq);

                // 刷新上下文
                context = refreshContext(context, docId);

                // 更新单元格内容
                if (columnData.getCells() != null && !columnData.getCells().isEmpty()) {
                    int newColIndex = (actualPosition == -1) ? currentColumnCount + i : actualPosition;

                    for (int row = 0; row < Math.min(columnData.getCells().size(), rowCount); row++) {
                        String cellValue = columnData.getCells().get(row);
                        if (cellValue != null && !cellValue.isEmpty()) {
                            String cellBlockId = cellLocator.apply(context, new int[]{row, newColIndex});
                            updateCellContentInternal(context, cellBlockId, cellValue);
                        }
                    }
                }
            }

            logger.info("成功向普通表格添加{}列", columns.size());

        } catch (TableException e) {
            throw e;
        } catch (Exception e) {
            throw new TableException("(add columns to normal table: " + e.getMessage());
        }
    }

    /**
     * 删除表格列
     */
    public void deleteTableColumns(TableContext context, int startCol, int endCol)
            throws TableException {
        // 接口定义从1开始，需要转换
        startCol--;

        logger.debug("删除 columns {} to {} from normal table", startCol, endCol);

        try {
            String tableBlockId = context.getTableBlockId();
            String docId = context.getDocumentId();

            // 构建删除列请求
            DeleteTableColumnsRequest deleteReq = DeleteTableColumnsRequest.newBuilder()
                    .columnStartIndex(startCol)
                    .columnEndIndex(endCol)
                    .build();

            UpdateBlockRequest updateReq = UpdateBlockRequest.newBuilder()
                    .blockId(tableBlockId)
                    .deleteTableColumns(deleteReq)
                    .build();

            PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                    .documentId(docId)
                    .blockId(tableBlockId)
                    .documentRevisionId(-1)
                    .updateBlockRequest(updateReq)
                    .build();

            // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
            client.docx().patchDocumentBlock(patchReq);

            logger.info("成功从普通表格删除第{}到第{}列", startCol, endCol);

        } catch (TableException e) {
            throw e;
        } catch (Exception e) {
            throw new TableException("(delete table columns: " + e.getMessage());
        }
    }

    // ========== 私有辅助方法 ==========

    /**
     * 刷新上下文
     */
    private TableContext refreshContext(TableContext context, String docId)
            throws DocumentOperationException {
        BlockContext contextNew = new BlockContext(client, docId);
        return new TableContext(docId, contextNew, context.getTableBlock());
    }

    /**
     * 内部方法：更新单元格内容
     */
    private void updateCellContentInternal(TableContext context, String cellBlockId, String value)
            throws TableException {
        logger.debug("更新 cell {} with value: {}", cellBlockId, value);

        try {
            BlockContext blockContext = context.getBlockContext();

            // 获取单元格Block
            Block cellBlock = blockContext.getBlockById(cellBlockId);
            if (cellBlock == null) {
                throw new TableException("单元格 block 未找到: " + cellBlockId);
            }

            // 获取单元格的子Block（通常是Text Block）
            List<Block> children = blockContext.findChildrenBlocks(cellBlockId);
            if (children.isEmpty()) {
                throw new TableException("单元格 has no text block");
            }

            // 更新第一个文本Block
            Block textBlock = children.get(0);
            String textBlockId = textBlock.getBlockId();

            // 创建新的文本元素
            TextElement[] elements = BlockUtils.createTextElements(value);

            // 构建更新请求
            UpdateTextElementsRequest updateReq = UpdateTextElementsRequest.newBuilder()
                    .elements(elements)
                    .build();

            UpdateBlockRequest blockUpdateReq = UpdateBlockRequest.newBuilder()
                    .blockId(textBlockId)
                    .updateTextElements(updateReq)
                    .build();

            PatchDocumentBlockReq patchReq = PatchDocumentBlockReq.newBuilder()
                    .documentId(context.getDocumentId())
                    .blockId(textBlockId)
                    .updateBlockRequest(blockUpdateReq)
                    .build();

            // patchDocumentBlock现在直接返回Block对象，失败时抛出FeishuApiException
            client.docx().patchDocumentBlock(patchReq);

            logger.debug("单元格内容更新成功");

        } catch (Exception e) {
            throw new TableException("(更新单元格内容: " + e.getMessage());
        }
    }
}
